home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / Apple Location Manager / Sources / Sample.c next >
Encoding:
Text File  |  1998-01-09  |  19.7 KB  |  732 lines  |  [TEXT/CWIE]

  1. /*
  2.      File:        Sample.c
  3.  
  4.      Contains:    Location Manager SDK Sample main code...
  5.  
  6.      Version:    ALM SDK 2.0
  7.                  Package:    Location Manager SDK 2.0
  8.  
  9.      Copyright:    © 1996-1997 by Apple Computer, Inc.
  10.                  All rights reserved.
  11.  
  12.      Bugs?:        Please include the the file and version information (from above) with
  13.                  the problem description.  Developers belonging to one of the Apple
  14.                  developer programs can submit bug reports to:
  15.  
  16.                      devsupport@apple.com
  17.  
  18. */
  19.  
  20. // ------------------------------------------------------------------------------------------------- 
  21.  
  22. #include    <ConditionalMacros.h>
  23.  
  24. // We recommend using the most updated headers currently available; at this writing, that is
  25. // Universal Headers 3.0.1.  More recent editions should work as well; if you want to use older
  26. // headers for some reason, it should be possible, but you're on your own and other parts of this
  27. // sample may need to change...
  28.  
  29. #if        !defined (UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0301)
  30.  
  31.     #error    "Please use header files 3.0.1 or newer"
  32.  
  33. #endif    // updated headers...
  34.  
  35. // Having gotten _that_ out of the way, let's be sure that nobody fiddled with the project
  36. // settings by accident...
  37.  
  38. #if            !TARGET_CPU_68K | TARGET_RT_MAC_CFM
  39.  
  40.     #error        This project MUST be classic 68K!
  41.  
  42. #endif        // not 68K classic build
  43.  
  44. // ------------------------------------------------------------------------------------------------- 
  45.  
  46. // Module Include...
  47.  
  48. #include    "Sample.h"
  49.  
  50. // Project Includes...
  51.  
  52. #include    "Utilities.h"
  53.  
  54. // MacOS Includes...
  55.  
  56. #define        ALM_BASENAME()
  57. #define        ALM_GLOBALS()        GlobalsHandle
  58.  
  59. #include    <Components.h>
  60. #include    <Fonts.h>
  61. #include    <LocationManager.k.h>
  62. #include    <PLStringFuncs.h>
  63. #include    <Resources.h>
  64. #include    <TextUtils.h>
  65.  
  66. // ------------------------------------------------------------------------------------------------- 
  67.  
  68. // Readability Constants...
  69.  
  70. #define        kInvalidFunction            ((ComponentFunctionUPP) -1)
  71.  
  72. #define        kDefaultINTLresources        NULL
  73. #define        kNoSeconds                    false
  74.  
  75. #define        kAllocateMemory                NULL
  76. #define        kPlaceInFront                (WindowPtr)-1
  77.  
  78. #define        kUseStandardFilterProc        NULL
  79.  
  80. // ------------------------------------------------------------------------------------------------- 
  81.  
  82. // Local prototypes...
  83.  
  84. static Boolean
  85. CallSupported (SInt16 selector);
  86.     // Return true if the specified selector code is one this module supports...
  87. static ComponentResult
  88. HandleComponentManagerCall (ComponentParameters* params, SInt16 selector);
  89.     // Dispatch a component manager call (selector < 0)...
  90. static ComponentResult
  91. HandleLocationManagerCall (ComponentParameters* params, SInt16 selector, 
  92.         Handle globals);
  93.     // Dispatch a Location Manager specific call...
  94.  
  95. // Component prototypes...
  96.  
  97. static pascal ComponentResult
  98. Open (ComponentInstance self);
  99.     // Initialize the modules's global variables, etc...
  100. static pascal ComponentResult 
  101. Close (ComponentInstance self);
  102.     // Deinitialize the modules's global variables...
  103.  
  104. // ------------------------------------------------------------------------------------------------- 
  105.  
  106. // Main entry point (interface as expected by component manager)...
  107.  
  108. pascal ComponentResult
  109. main (ComponentParameters* params, Handle storage) {
  110.  
  111.     // We dispatch the calls from here; also, for ALM calls, we'll make sure the current
  112.     // resource fork is ours...
  113.  
  114.     ComponentResult            result;
  115.     SInt16                    selector     = params->what;
  116.     SInt16                    svResFile    = CurResFile ();
  117.  
  118.     if (selector < 0) {
  119.         // Component manager request codes are negative...
  120.         result = HandleComponentManagerCall (params, selector);
  121.     } else {
  122.         // ALM selectors...
  123.         if (storage != NULL) {
  124.             UseResFile ((**(GlobalsHandle) storage).resFile);
  125.         } // if
  126.         result = HandleLocationManagerCall (params, selector, storage);
  127.     } // if
  128.             
  129.     UseResFile (svResFile);
  130.  
  131.     return result;
  132.  
  133. } // main
  134.  
  135. // ------------------------------------------------------------------------------------------------- 
  136.  
  137. static Boolean
  138. CallSupported (SInt16 selector) {
  139.  
  140.     Boolean        response;
  141.  
  142.     switch (selector) {
  143.         case kALMGetCurrentSelect:
  144.         case kALMSetCurrentSelect:
  145.         case kALMCompareSettingSelect:
  146.         case kALMDescribeSettingSelect:
  147.         case kALMDescribeErrorSelect:
  148.         case kALMEditSettingSelect:
  149.         case kALMImportExportSelect:
  150.         case kALMGetInfoSelect:
  151.         case kALMGetScriptInfoSelect:
  152.             response = true;
  153.             break;
  154.         default:
  155.             response = false;
  156.             break;
  157.     } // switch
  158.  
  159.     return response;
  160.  
  161. } // CallSupported
  162.  
  163. // ------------------------------------------------------------------------------------------------- 
  164.  
  165. static ComponentResult
  166. HandleComponentManagerCall (ComponentParameters* params, SInt16 selector) {
  167.  
  168.     ComponentResult            result     = (ComponentResult) noErr;
  169.     ComponentFunctionUPP     func     = NULL;
  170.  
  171.     switch (selector) {
  172.  
  173.         case kComponentOpenSelect:
  174.             func = (ComponentFunctionUPP) Open;
  175.             break;
  176.         case kComponentCloseSelect:
  177.             func = (ComponentFunctionUPP) Close;
  178.             break;
  179.         case kComponentCanDoSelect:
  180.             result = CallSupported (*(SInt16*) params->params);
  181.             break;
  182.         case kComponentVersionSelect:
  183.             result = kModuleVersion;
  184.             break;
  185.         case kComponentRegisterSelect:
  186.             result = false;            // false means "yes, please register me"    
  187.             break;
  188.         case kComponentTargetSelect :
  189.         case kComponentUnregisterSelect :
  190.             result = badComponentSelector;
  191.             break;
  192.             
  193.     } // switch
  194.     
  195.     if (func != NULL) {
  196.         result = CallComponentFunction (params, func);
  197.     } // if
  198.  
  199.     return result;
  200.  
  201. } // HandleComponentManagerCall
  202.  
  203. // ------------------------------------------------------------------------------------------------- 
  204.  
  205. static ComponentResult
  206. HandleLocationManagerCall (ComponentParameters* params, SInt16 selector, Handle globals) {
  207.  
  208.     ComponentResult            result     = (ComponentResult) noErr;
  209.     ComponentFunctionUPP     func     = NULL;
  210.  
  211.     switch (selector) {
  212.     
  213.         case kALMGetCurrentSelect:
  214.             func = (ComponentFunctionUPP) GetCurrent;
  215.             break;
  216.         case kALMSetCurrentSelect:
  217.             func = (ComponentFunctionUPP) SetCurrent;
  218.             break;
  219.         case kALMCompareSettingSelect:
  220.             func = (ComponentFunctionUPP) CompareSetting;
  221.             break;
  222.         case kALMEditSettingSelect:
  223.             func = (ComponentFunctionUPP) EditSetting;
  224.             break;
  225.         case kALMDescribeSettingSelect:
  226.             func = (ComponentFunctionUPP) DescribeSetting;
  227.             break;
  228.         case kALMDescribeErrorSelect:
  229.             func = (ComponentFunctionUPP) DescribeError;
  230.             break;
  231.         case kALMImportExportSelect:
  232.             func = (ComponentFunctionUPP) ImportExport;
  233.             break;
  234.         case kALMGetScriptInfoSelect:
  235.             func = (ComponentFunctionUPP) GetScriptInfo;
  236.             break;
  237.         case kALMGetInfoSelect:
  238.             func = (ComponentFunctionUPP) GetInfo;
  239.             break;
  240.         default:
  241.             func = kInvalidFunction;
  242.             break;
  243.             
  244.     } // switch
  245.  
  246.     if (func == kInvalidFunction) {
  247.         result = badComponentSelector;
  248.     } else if (func != NULL) {
  249.         result = CallComponentFunctionWithStorage (globals, params, func);
  250.     } // if
  251.  
  252.     return result;
  253.  
  254. } // HandleLocationManagerCall
  255.  
  256. // ------------------------------------------------------------------------------------------------- 
  257.  
  258. static    pascal ComponentResult
  259. Open (ComponentInstance self) {
  260.  
  261.     // Keep the Open routine lightweight, and only fail in the case of dire
  262.     // emergencies that indicate a major problem; under ALM 2.0, you might wish to return an
  263.     // error here to quietly suppress your module from being usable--for example if you require
  264.     // Infrared hardware found only on some models of computer--but it is generally better to
  265.     // _succeed_ here and describe an _error_ from your GetCurrent call...
  266.  
  267.     OSErr                err        = noErr;
  268.     GlobalsHandle        globals    = (GlobalsHandle) NewHandle (sizeof (Globals));
  269.     
  270.     if (globals != NULL) {
  271.     
  272.         SetComponentInstanceStorage (self, (Handle) globals);
  273.     
  274.         (**globals).fileCount    = 0;
  275.         (**globals).self         = (Component) self;
  276.         (**globals).resFile        = OpenComponentResFile ((Component) self);
  277.     
  278.         err = ResError ();
  279.     
  280.     } else {
  281.         err = memFullErr;
  282.     } // if
  283.  
  284.     return (ComponentResult) err;
  285.     
  286. } // Open
  287.  
  288. // ------------------------------------------------------------------------------------------------- 
  289.  
  290. static    pascal ComponentResult
  291. Close (ComponentInstance self) {
  292.  
  293.     OSErr                err        = noErr;
  294.     GlobalsHandle        globals    = (GlobalsHandle) GetComponentInstanceStorage (self);
  295.  
  296.     if (globals != NULL) {
  297.  
  298.         SInt16        resFile = (**globals).resFile;
  299.  
  300.         if (resFile > 0)    {    
  301.             CloseComponentResFile (resFile);
  302.             (**globals).resFile = 0;
  303.         } // if
  304.  
  305.         DisposeHandle ((Handle) globals);
  306.         SetComponentInstanceStorage (self, NULL);
  307.  
  308.     } // if
  309.  
  310.     return (ComponentResult) err;
  311.     
  312. } // Close
  313.  
  314. // ------------------------------------------------------------------------------------------------- 
  315.  
  316. static pascal ComponentResult    
  317. GetCurrent (GlobalsHandle globals, Handle setting) {
  318.  
  319.     OSErr                err        = noErr;
  320.  
  321.     // To get the current settings, we need to go off to the resource and make FSSpecs
  322.     // for all of the files we care about, then read in their settings...
  323.  
  324.     err = ConfirmFSSpecs (globals);
  325.  
  326.     if (err == noErr) {
  327.         err = ReadSetting (globals, (SettingHandle) setting);
  328.     } // if
  329.  
  330.     return (ComponentResult) err;
  331.  
  332. } // GetCurrent
  333.  
  334. // ------------------------------------------------------------------------------------------------- 
  335.  
  336. static pascal ComponentResult
  337. SetCurrent (GlobalsHandle globals, Handle setting, ALMRebootFlags* flags) {
  338.  
  339.     OSErr                err                = noErr;
  340.     Handle                tempSetting        = NewHandle (1);
  341.  
  342.     *flags = kALMNoChange;        // Safe value...
  343.  
  344.     // Before we go off and change the setting, see if it's the current setting; if
  345.     // the settings are _not_ the same, we'll assume "kALMAvailableNow" and let
  346.     // UseSetting escalate it, based on any of the specific files...
  347.         
  348.     if (tempSetting != NULL) {
  349.         err = (OSErr) GetCurrent (globals, tempSetting);
  350.         if (err == noErr) {
  351.             Boolean        lookTheSame;
  352.             err = CompareSetting (globals, tempSetting, setting, &lookTheSame);
  353.             if ((err == noErr) && !lookTheSame) {
  354.                 *flags = kALMAvailableNow;
  355.                 err = UseSetting (globals, (SettingHandle) setting, flags);
  356.             } // if
  357.         } // if
  358.     } else {
  359.         err = memFullErr;
  360.     } // if
  361.  
  362.     if (tempSetting != NULL) {
  363.         DisposeHandle (tempSetting);    
  364.     } // if
  365.  
  366.     return (ComponentResult) err;
  367.  
  368. } // SetCurrent
  369.  
  370. // ------------------------------------------------------------------------------------------------- 
  371.  
  372. static pascal ComponentResult
  373. CompareSetting (GlobalsHandle globals, Handle setting1, Handle setting2, Boolean* equal) {
  374.  
  375. #ifndef    __SC__
  376. #pragma unused (globals)
  377. #endif    // __SC__
  378.  
  379.     OSErr                err            = noErr;
  380.     SInt8                svState1    = HGetState (setting1);
  381.     SInt8                svState2    = HGetState (setting2);
  382.     SettingPtr            set1;
  383.     SettingPtr            set2;
  384.  
  385.     *equal = true;
  386.  
  387.     // To see if two settings are the same, all we do is compare their dates...
  388.     
  389.     HLock (setting1);
  390.     HLock (setting2);
  391.     
  392.     set1 = (SettingPtr) *setting1;
  393.     set2 = (SettingPtr) *setting2;
  394.     
  395.     do {
  396.     
  397.         UInt32    fileIndex;
  398.         UInt32    fileCount = set1->fileCount;
  399.     
  400.         // If the settings versions are not the same, we have a problem...
  401.         
  402.         if (set1->version != set2->version) {
  403.             *equal = false;
  404.             break;
  405.         } // if
  406.  
  407.         // If the number of files modified is not the same, we have a problem...
  408.     
  409.         if (fileCount != set2->fileCount) {
  410.             *equal = false;
  411.             break;
  412.         } // if
  413.         
  414.         // Now, if the modification dates (or creation dates) changed, we'll take
  415.         // that as a signal...
  416.         
  417.         for (fileIndex = 0; fileIndex < fileCount; fileIndex += 1) {
  418.         
  419.             FileInfoPtr        fileInfo1;
  420.             FileInfoPtr        fileInfo2;
  421.         
  422.             fileInfo1 = &set1->fileInfo[fileIndex];
  423.             fileInfo2 = &set2->fileInfo[fileIndex];
  424.         
  425.             if ((fileInfo1->dateModified != fileInfo2->dateModified) ||
  426.                     (fileInfo1->dateCreated != fileInfo2->dateCreated)) {
  427.                 *equal = false;
  428.                 break;
  429.             } // if
  430.         } // for
  431.         
  432.     } while (false); // Loop once...
  433.     
  434.     HSetState (setting2, svState2);
  435.     HSetState (setting1, svState1);
  436.  
  437.     return (ComponentResult) err;
  438.  
  439. } // CompareSetting
  440.  
  441. // ------------------------------------------------------------------------------------------------- 
  442.  
  443. static pascal ComponentResult
  444. EditSetting (GlobalsHandle globals, Handle setting) {
  445.  
  446.     OSErr                err                = noErr;
  447.     UInt32                 savedA5;
  448.     QDGlobals            mqd;                    // So we can put up an alert...
  449.     QDGlobalsPtr        moduleQuickdraw = &mqd;
  450.     DialogPtr            theDialog         = NULL;
  451.  
  452.     // In ALM 2.0, if you don't support EditSetting, the control panel will display a default
  453.     // error message if the user tries to edit your setting.  Of course, how to edit the setting
  454.     // is entirely dependant on the content of the setting.  In the case of this sample, we
  455.     // really don't know what the meaning of the preference file is, but we can, at the very least,
  456.     // give the user a more helpful error message...
  457.     
  458.     savedA5 = SetA5 ((UInt32) &moduleQuickdraw);
  459.  
  460.     // Initialize a QD world...
  461.     
  462.     InitGraf (&mqd.thePort);        // always init _our_ QD structure
  463.     InitFonts ();
  464.     InitWindows ();
  465.     InitMenus ();
  466.     TEInit ();
  467.     InitDialogs (NULL);
  468.     InitCursor ();
  469.  
  470.     // Get and display the "sorry" dialog...
  471.  
  472.     theDialog = GetNewDialog (kEditMessageRsrcID, kAllocateMemory, kPlaceInFront);
  473.  
  474.     if (theDialog != NULL) {
  475.     
  476.         SInt16        itemHit;
  477.         GrafPtr        svPort;
  478.  
  479.         GetPort (&svPort);
  480.         SetPort (theDialog);
  481.         SetDialogDefaultItem (theDialog, kEditOpenButton);
  482.         SetDialogCancelItem (theDialog, kEditCancelButton);
  483.         ShowWindow (theDialog);
  484.         
  485.         // Loop until closed; note that, as long as we use the standard filter proc, 
  486.         // the ALM control panel will manage launches and moveable-modal things for us...
  487.         
  488.         do {
  489.             ModalDialog (kUseStandardFilterProc, &itemHit);
  490.             switch (itemHit) {
  491.                 case kEditCancelButton:
  492.                     err = userCanceledErr;
  493.                     break;
  494.                 case kEditOpenButton:
  495.                     err = LaunchApplications (launchContinue | launchNoFileFlags);
  496.                     break;
  497.                 case kEditApplyButton:
  498.                     err = GetCurrent (globals, setting);
  499.                     break;        
  500.             } // switch
  501.         } while (itemHit != kEditCancelButton && itemHit != kEditApplyButton);
  502.     
  503.         DisposeDialog (theDialog);
  504.         SetPort (svPort);
  505.     
  506.     } else {
  507.     
  508.         err = resNotFound;
  509.     
  510.     } // if
  511.  
  512.     // Restore a5...
  513.  
  514.     (void) SetA5 (savedA5);
  515.  
  516.     return (ComponentResult) err;
  517.  
  518. } // EditSetting
  519.  
  520. // ------------------------------------------------------------------------------------------------- 
  521.  
  522. static pascal ComponentResult
  523. DescribeSetting (GlobalsHandle globals, Handle setting, CharsHandle text) {
  524.  
  525.     OSErr                err        = noErr;
  526.     SettingHandle        theSet    = (SettingHandle) setting;
  527.     UInt32                dateMod;
  528.     Str255                dateModStr;
  529.     Str255                timeModStr;
  530.     Str63                firstFileStr;
  531.     Str255                templateStr;
  532.  
  533.     // Not entirely sure how to describe the settings, but we'll take the approach
  534.     // of using the first file name and its modification date as "sufficient" info...
  535.     
  536.     err = ConfirmFSSpecs (globals);
  537.  
  538.     if (err == noErr) {
  539.  
  540.         SInt8        svState;
  541.         UInt8        strSize;
  542.         
  543.         dateMod = (**theSet).fileInfo[0].dateModified;
  544.         
  545.         DateString (dateMod, shortDate,  dateModStr, kDefaultINTLresources);
  546.         TimeString (dateMod, kNoSeconds, timeModStr, kDefaultINTLresources);
  547.         GetIndString (templateStr, kSampleMiscStrRsrcID, kSampleDescribeTemplateIdx);
  548.  
  549.         svState = HGetState ((Handle) globals);
  550.         HLock ((Handle) globals);
  551.         PLstrcpy (firstFileStr, (**globals).theFiles[0].name);
  552.         HSetState ((Handle) globals, svState);
  553.  
  554.         InsParamStr ("\p^0", firstFileStr, templateStr);
  555.         InsParamStr ("\p^1", timeModStr, templateStr);
  556.         InsParamStr ("\p^2", dateModStr, templateStr);
  557.         
  558.         strSize = StrLength (templateStr);
  559.         SetHandleSize ((Handle) text, strSize);
  560.         err = MemError ();
  561.         if (err == noErr) {
  562.             BlockMoveData (&templateStr[1], *text, strSize);
  563.         } // if
  564.     
  565.     } // if
  566.  
  567.     return (ComponentResult) err;
  568.  
  569. } // DescribeSetting
  570.  
  571. // ------------------------------------------------------------------------------------------------- 
  572.  
  573. static pascal ComponentResult
  574. DescribeError (GlobalsHandle globals, OSErr lastErr, Str255 errStr) {
  575.  
  576. #ifndef    __SC__
  577. #pragma unused (globals)
  578. #endif    // __SC__
  579.  
  580.     OSErr                err        = noErr;
  581.  
  582.     // We're just going to be very superficial about this, and deal with a very few
  583.     // "plain text" messages only. We could get fancy, and try to be a bit more 
  584.     // descriptive...
  585.  
  586.     if ((lastErr > 0) && (lastErr <= kSampleBiggestKnownIdx)) {
  587.         GetIndString (errStr, kSampleErrStrRsrcID, lastErr);
  588.     } else {
  589.         err = paramErr;    // Get ALM to generate default "error number" text...
  590.     } // if
  591.  
  592.     return (ComponentResult) err;
  593.  
  594. } // DescribeError
  595.  
  596. // ------------------------------------------------------------------------------------------------- 
  597.  
  598. static pascal ComponentResult
  599. ImportExport (GlobalsHandle globals, Boolean import, Handle setting, SInt16 resRefNum) {
  600.  
  601.     OSErr                err            = noErr;
  602.     SInt16                svResFile    = CurResFile ();
  603.  
  604.     // Not a lot of work to do here; but if we are importing _and_ the current settings
  605.     // on the machine match the import, we have a problem in that our mechanism doesn't
  606.     // let us distinguish the new setting properly. It is possible that the user would
  607.     // prefer to overwrite the existing settings, but we won't handle that case.
  608.     
  609.     UseResFile (resRefNum);    // Need to do this if we use separate resources for import/export...
  610.     
  611.     // If this were a real module, your might need to grab more information from this
  612.     // machine in order to carry the setting over to another machine; for example, the
  613.     // extension set module that comes with ALM only stores the _name_ of an extension
  614.     // manager set, which is good enough for using on one machine, but when that setting
  615.     // is exported, the names of all the on/off extensions get spooled away in a separate
  616.     // resource (which the module adds to the "resRefNum" resource fork)...
  617.     
  618.     if (import) {
  619.     
  620.         Handle        tempSetting        = NewHandle (1);
  621.         
  622.         if (tempSetting != NULL) {
  623.             err = (OSErr) GetCurrent (globals, tempSetting);
  624.             if (err == noErr) {
  625.                 Boolean        lookTheSame;
  626.                 err = CompareSetting (globals, tempSetting, setting, &lookTheSame);
  627.                 if ((err == noErr) && lookTheSame) {
  628.                     err = kSampleImportPrefDatesIdx;
  629.                 } // if
  630.             } // if
  631.         } else {
  632.             err = memFullErr;
  633.         } // if
  634.     
  635.         if (tempSetting != NULL) {
  636.             DisposeHandle (tempSetting);    
  637.         } // if
  638.  
  639.     } // if
  640.  
  641.     UseResFile (svResFile);
  642.  
  643.     return (ComponentResult) err;
  644.  
  645. } // ImportExport
  646.  
  647. // ------------------------------------------------------------------------------------------------- 
  648.  
  649. static pascal ComponentResult
  650. GetScriptInfo (GlobalsHandle globals, ALMScriptManagerInfo* info) {
  651.  
  652. #ifndef    __SC__
  653. #pragma unused (globals)
  654. #endif    // __SC__
  655.  
  656.     OSErr                                err            = noErr;
  657.     ALMAltScriptManagerInfoHandle        scriptInfo    = NULL;
  658.  
  659.     // We stored this stuff in a resource, so it can be localized easily; we have to do a bit of
  660.     // translation, though, from the alternate format to the ALM format (fortunately
  661.     // the alternate format is given to us in the headers!)...
  662.     
  663.     scriptInfo = (ALMAltScriptManagerInfoHandle) 
  664.                 GetResource (kALMAltScriptManagerInfoRsrcType, kALMAltScriptManagerInfoRsrcID);
  665.     
  666.     if (scriptInfo != NULL) {
  667.  
  668.         HLock ((Handle) scriptInfo);
  669.         
  670.         info->version         = (**scriptInfo).version;
  671.         info->scriptCode     = (**scriptInfo).scriptCode;
  672.         info->regionCode     = (**scriptInfo).regionCode;
  673.         info->langCode         = (**scriptInfo).langCode;
  674.         info->fontSize         = (**scriptInfo).fontSize;
  675.         GetFNum ((**scriptInfo).fontName, &info->fontNum);
  676.         
  677.         HUnlock ((Handle) scriptInfo);
  678.  
  679.     } else {
  680.         err = ResError ();
  681.     } // if
  682.  
  683.     if (scriptInfo != NULL) {
  684.         ReleaseResource ((Handle) scriptInfo);
  685.     } // if
  686.  
  687.     return (ComponentResult) err;
  688.  
  689. } // GetScriptInfo
  690.  
  691. // ------------------------------------------------------------------------------------------------- 
  692.  
  693. static pascal ComponentResult
  694. GetInfo (GlobalsHandle globals, CharsHandle* text, STHandle* style, ModalFilterUPP filter) {
  695.  
  696. #ifndef    __SC__
  697. #pragma unused (globals, filter)
  698. #endif    // __SC__
  699.  
  700.     OSErr                err        = noErr;
  701.  
  702.     // This code is pretty cookie-cutter, unless you want to make it context-sensitive...
  703.  
  704.     do {
  705.     
  706.         *text = (CharsHandle) Get1Resource ('TEXT', kGetInfoRsrcID);
  707.         err = ResError ();
  708.         if (err != noErr) {
  709.             break;
  710.         } else if (*text == NULL) {
  711.             err = resNotFound;
  712.             break;
  713.         } // if
  714.         *style = (STHandle) Get1Resource ('styl', kGetInfoRsrcID);
  715.         err = ResError ();
  716.         if (err != noErr) {
  717.             break;
  718.         } else if (*style == NULL) {
  719.             err = resNotFound;
  720.             break;
  721.         } // if
  722.         DetachResource ((Handle) *text);
  723.         DetachResource ((Handle) *style);
  724.     
  725.     } while (false);    // execute once...
  726.     
  727.     return (ComponentResult) err;
  728.  
  729. } // GetInfo
  730.  
  731. // ------------------------------------------------------------------------------------------------- 
  732.